﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using MySql.Data.MySqlClient;

namespace SistemaFinanceiro.classes.core
{
    public class GenericoMySQLDAO<T> : IGenericoDAO<T> where T : GenericoClasse
    {
        #region IGenericoDAO<T> Members

        public T Inserir(T item)
        {
            return null;
        }

        public void Remover(T item)
        {
        }

        public T Salvar(T item)
        {
            return null;
        }

        public List<T> Listar()
        {
            MySqlConnection con = getConnection();

            StringBuilder builder = new StringBuilder();
            builder.Append("SELECT * FROM ");
            builder.Append(GetTableName());
            MySqlCommand cmd = new MySqlCommand(builder.ToString(), con);

            MySqlDataReader reader = cmd.ExecuteReader();
            return ListarRegistros(reader);

        }

        private List<T> ListarRegistros(MySqlDataReader reader)
        {
            List<T> lista = new List<T>();
            while (reader.Read())
            {
                T entity = (T)Activator.CreateInstance(typeof(T));
                for (int col = 0; col < reader.FieldCount; col++)
                {
                    String nomePropriedade = GetFieldName(reader.GetName(col));

                    Object valor = reader.GetValue(col);

                    MethodInfo metodo = entity.GetType().GetMethod("set_" + nomePropriedade);
                    metodo.Invoke(entity, new Object[] { valor });
                }
                lista.Add(entity);
            }
            return lista;
        }

        public List<T> ListarPorPropriedade(string nomePropriedade, object valor)
        {
            throw new NotImplementedException();
        }

        public T ProcurarPorPropriedade(string nomePropriedade, object valor)
        {
            MySqlConnection con = getConnection();

            StringBuilder builder = new StringBuilder();
            builder.Append("SELECT * FROM ");
            builder.Append(GetTableName());
            builder.Append(" WHERE ");
            builder.Append(GetFieldTableName(nomePropriedade));
            builder.Append(" = '");
            builder.Append(valor);
            builder.Append("'");


            MySqlCommand cmd = new MySqlCommand(builder.ToString(), con);

            MySqlDataReader reader = cmd.ExecuteReader();
            List<T> lista = ListarRegistros(reader);
            if (lista.Count > 0)
            {
                return lista[0];
            }
            else
            {
                return null;

            }
        }

        private string GetFieldTableName(string propriedade)
        {
            Type tipo = typeof(T);
            Dictionary<string, string> fields = (Dictionary<string, string>)tipo.GetMethod("GetFields").Invoke(null, null);
            foreach (KeyValuePair<String, String> entry in fields)
            {
                string valor = (string)entry.Value;
                if (valor.ToLower().Equals(propriedade.ToLower()))
                {
                    string campo = entry.Key;
                    return campo;
                }
            }
            return null;
        }

        #endregion

        protected MySqlConnection getConnection()
        {
            MySqlConnection dataConnection = new MySqlConnection();
            dataConnection.ConnectionString = "database=SIS_FINANC;server=localhost;uid=root;pwd=''";
            dataConnection.Open();
            return dataConnection;
        }

        private string GetTableName()
        {
            Type tipo = typeof(T);
            string tableName = (string)tipo.GetMethod("GetTableName").Invoke(null, null);
            return tableName;
        }

        private string GetFieldName(string propriedade)
        {
            Type tipo = typeof(T);
            Dictionary<string, string> fields = (Dictionary<string, string>)tipo.GetMethod("GetFields").Invoke(null, null);


            string campo = null;
            fields.TryGetValue(propriedade, out campo);
            return campo;
        }
    }
}
